﻿////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// <copyright>Copyright 2008-2011 Andreas Huber Doenni</copyright>
// Distributed under the Microsoft Public License (Ms-PL).
// See accompanying file License.txt or copy at http://mews.codeplex.com/license.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

namespace Mews.Net
{
    using System;
    using System.Globalization;
    using System.Reflection;

    /// <summary>Provides <b>generic</b> means to convert a string into a <typeparamref name="TParsable"/> object.
    /// </summary>
    /// <typeparam name="TParsable">The type that is parsed from a string. This must either offer a public static method
    /// called "Parse" accepting a single <see cref="string"/> parameter or be the <see cref="string"/> type itself.
    /// </typeparam>
    internal static class Parser<TParsable>
    {
        private static readonly Func<string, TParsable> parseMethod = GetParseMethod();

        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        internal static TParsable Parse(string s)
        {
            return parseMethod(s);
        }

        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        private static Func<string, TParsable> GetParseMethod()
        {
            MethodInfo method = typeof(string) == typeof(TParsable) ?
                ParserHelper.GetParseMethod<ParserHelper>("ParseString", true) :
                ParserHelper.GetParseMethod<TParsable>("Parse", false);

            if (method == null)
            {
                return s =>
                {
                    throw new InvalidOperationException(
                        typeof(TParsable).FullName + " does not offer a public static Parse method.");
                };
            }
            else
            {
                return (Func<string, TParsable>)
                    Delegate.CreateDelegate(typeof(Func<string, TParsable>), null, method);
            }
        }
    }
}
